package cn.tang.tframe.sdm.web.shiro.session;

import cn.tang.tframe.springredis.QtProjectRedisClient;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.util.CollectionUtils;
import org.crazycake.shiro.SerializeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author tanghc
 */
public class AppRedisCache <K, V extends Serializable> implements Cache<K, V> {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	/**
	 * The Redis key prefix for the sessions
	 */
	private String keyPrefix = "shiro_redis_session:";

	public AppRedisCache(String keyPrefix) {
		this.keyPrefix = keyPrefix;
	}

	/**
	 * 获得byte[]型的key
	 * @param key
	 * @return
	 */
	private byte[] getByteKey(K key){
		if(key instanceof String){
			String preKey = this.keyPrefix + key;
			return preKey.getBytes();
		}else{
			return SerializeUtils.serialize(key);
		}
	}
	private String getKey(K key){
		if(key instanceof String){
			String preKey = this.keyPrefix + key;
			return preKey;
		}else{
			return key.toString();
		}
	}

	@Override
	public V get(K key) throws CacheException {
		logger.debug("根据key从Redis中获取对象 key [" + key + "]");
		try {
			if (key == null) {
				return null;
			}else{
				return (V) QtProjectRedisClient.getSpringRedisCache().get(getKey(key));
			}
		} catch (Throwable t) {
			throw new CacheException(t);
		}

	}

	@Override
	public V put(K key, V value) throws CacheException {
		logger.debug("根据key从存储 key [" + key + "]");
		try {
			QtProjectRedisClient.getSpringRedisCache().set(getKey(key), value);
			return value;
		} catch (Throwable t) {
			throw new CacheException(t);
		}
	}

	@Override
	public V remove(K key) throws CacheException {
		logger.debug("从redis中删除 key [" + key + "]");
		try {
			V previous = get(key);
			QtProjectRedisClient.getSpringRedisCache().del(getKey(key));
			return previous;
		} catch (Throwable t) {
			throw new CacheException(t);
		}
	}

	@Override
	public void clear() throws CacheException {
		logger.debug("从redis中删除所有元素");
		try {
			QtProjectRedisClient.getSpringRedisCache().del(this.keyPrefix + "*");
		} catch (Throwable t) {
			throw new CacheException(t);
		}
	}

	@Override
	public int size() {
		try {
			Set<String> keys = QtProjectRedisClient.getSpringRedisCache().keys(this.keyPrefix + "*");
			return null != keys?keys.size():0;
		} catch (Throwable t) {
			throw new CacheException(t);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public Set<K> keys() {
		try {
			Set<String> keys = QtProjectRedisClient.getSpringRedisCache().keys(this.keyPrefix + "*");
			if (CollectionUtils.isEmpty(keys)) {
				return Collections.emptySet();
			}else{
				Set<K> newKeys = new HashSet<K>();
				for(String key:keys){
					newKeys.add((K)key);
				}
				return newKeys;
			}

		} catch (Throwable t) {
			throw new CacheException(t);
		}
	}

	@Override
	public Collection<V> values() {
		try {
			Set<String> keys = QtProjectRedisClient.getSpringRedisCache().keys(this.keyPrefix + "*");
			if (!CollectionUtils.isEmpty(keys)) {
				List<V> values = new ArrayList<V>(keys.size());
				for (String  key : keys) {
					V value = get((K)key);
					if (value != null) {
						values.add(value);
					}
				}
				return Collections.unmodifiableList(values);
			} else {
				return Collections.emptyList();
			}
		} catch (Throwable t) {
			throw new CacheException(t);
		}
	}

}
